#!/bin/bash
# Create initramfs image
# Author: Tomas M <http://www.linux-live.org/>
#

. ../config

INITRAMFS=/tmp/$LIVEKITNAME-initramfs-$$

# copy file to initramfs tree, including
# all library dependencies (as shown by ldd)
# $1 = file to copy (full path)
copy_including_deps()
{
   # if source doesn't exist or target exists, do nothing
   if [ ! -e "$1" -o -e "$INITRAMFS"/"$1" ]; then
      return
   fi

   cp -R --parents "$1" "$INITRAMFS"
   if [ -L "$1" ]; then
      DIR="$(dirname "$1")"
      LNK="$(readlink "$1")"
      copy_including_deps "$(cd "$DIR"; realpath -s "$LNK")"
   fi

   ldd "$1" 2>/dev/null | sed -r "s/.*=>|[(].*//g" | sed -r "s/^\\s+|\\s+\$//" \
     | while read LIB; do
        copy_including_deps "$LIB"
     done

   for MOD in $(find "$1" -type f | grep .ko); do
      for DEP in $(cat /$LMK/modules.dep | fgrep /$(basename $MOD):); do
         copy_including_deps "/$LMK/$DEP"
      done
   done

   shift
   if [ "$1" != "" ]; then
       copy_including_deps "$@"
   fi
}

rm -Rf $INITRAMFS
mkdir -p $INITRAMFS/{bin,dev,etc,lib,lib64,mnt,proc,root,run,sys,tmp,usr,var/log}
ln -s bin $INITRAMFS/sbin

cp static/busybox $INITRAMFS/bin
cp static/ncurses-menu $INITRAMFS/bin
cp static/mc $INITRAMFS/bin
cp static/eject $INITRAMFS/bin
cp static/mkfs.xfs.custom $INITRAMFS/bin
cp static/xfs_growfs $INITRAMFS/bin
cp static/mount.dynfilefs $INITRAMFS/bin/@mount.dynfilefs
cp static/mount.httpfs2 $INITRAMFS/bin/@mount.httpfs2
cp static/blkid $INITRAMFS/bin
chmod a+x $INITRAMFS/bin/*
mkdir -p $INITRAMFS/etc/modprobe.d
echo "options loop max_loop=32" >$INITRAMFS/etc/modprobe.d/local-loop.conf

$INITRAMFS/bin/busybox | grep , | grep -v Copyright | tr "," " " | while read LINE; do
   for TOOL in $LINE; do
      if [ ! -e $INITRAMFS/bin/$TOOL ]; then
         ln -s busybox $INITRAMFS/bin/$TOOL
      fi
   done
done
rm -f $INITRAMFS/{s,}bin/init

mknod $INITRAMFS/dev/console c 5 1
mknod $INITRAMFS/dev/null c 1 3
mknod $INITRAMFS/dev/ram0 b 1 0
mknod $INITRAMFS/dev/tty1 c 4 1
mknod $INITRAMFS/dev/tty2 c 4 2
mknod $INITRAMFS/dev/tty3 c 4 3
mknod $INITRAMFS/dev/tty4 c 4 4

#copy_including_deps /usr/bin/strace
#copy_including_deps /usr/bin/lsof

copy_including_deps /$LMK/kernel/fs/aufs
copy_including_deps /$LMK/kernel/fs/overlayfs
copy_including_deps /$LMK/kernel/fs/ext2
copy_including_deps /$LMK/kernel/fs/ext3
copy_including_deps /$LMK/kernel/fs/ext4
copy_including_deps /$LMK/kernel/fs/fat
copy_including_deps /$LMK/kernel/fs/nls
copy_including_deps /$LMK/kernel/fs/fuse
copy_including_deps /$LMK/kernel/fs/isofs
copy_including_deps /$LMK/kernel/fs/ntfs
copy_including_deps /$LMK/kernel/fs/ntfs3
copy_including_deps /$LMK/kernel/fs/reiserfs
copy_including_deps /$LMK/kernel/fs/squashfs

# crc32c is needed for ext4, but I don't know which one, add them all, they are small
find /$LMK/kernel/ | grep crc32c | while read LINE; do
   copy_including_deps $LINE
done

copy_including_deps /$LMK/kernel/drivers/staging/zsmalloc # needed by zram
copy_including_deps /$LMK/kernel/drivers/block/zram
copy_including_deps /$LMK/kernel/drivers/block/loop.*

# usb drivers
copy_including_deps /$LMK/kernel/drivers/usb/storage
copy_including_deps /$LMK/kernel/drivers/usb/host
copy_including_deps /$LMK/kernel/drivers/usb/common
copy_including_deps /$LMK/kernel/drivers/usb/core
copy_including_deps /$LMK/kernel/drivers/hid/usbhid
copy_including_deps /$LMK/kernel/drivers/hid/hid.*
copy_including_deps /$LMK/kernel/drivers/hid/uhid.*
copy_including_deps /$LMK/kernel/drivers/hid/hid-generic.*

# disk and cdrom drivers
copy_including_deps /$LMK/kernel/drivers/cdrom
copy_including_deps /$LMK/kernel/drivers/scsi/sr_mod.*
copy_including_deps /$LMK/kernel/drivers/scsi/sd_mod.*
copy_including_deps /$LMK/kernel/drivers/scsi/scsi_mod.*
copy_including_deps /$LMK/kernel/drivers/scsi/sg.*
copy_including_deps /$LMK/kernel/drivers/ata
copy_including_deps /$LMK/kernel/drivers/nvme
copy_including_deps /$LMK/kernel/drivers/mmc

# network support drivers
if [ "$NETWORK" = "true" ]; then
   # add all known ethernet drivers
   copy_including_deps /$LMK/kernel/drivers/net/ethernet
fi

# copy all custom-built modules
copy_including_deps /$LMK/updates

copy_including_deps /$LMK/modules.*

copy_including_deps /usr/share/terminfo/l/linux


find $INITRAMFS -name "*.ko.gz" -exec gunzip {} \;

# trim modules.order file. Perhaps we could remove it entirely
MODULEORDER="$(cd "$INITRAMFS/$LMK/"; find -name "*.ko" | sed -r "s:^./::g" | tr "\n" "|" | sed -r "s:[.]:.:g")"
cat $INITRAMFS/$LMK/modules.order | sed -r "s/.ko.gz\$/.ko/" | grep -E "$MODULEORDER"/foo/bar > $INITRAMFS/$LMK/_
mv $INITRAMFS/$LMK/_ $INITRAMFS/$LMK/modules.order

depmod -b $INITRAMFS $KERNEL

echo "root::0:0::/root:/bin/sh" >$INITRAMFS/etc/passwd
touch $INITRAMFS/etc/{m,fs}tab

cp init $INITRAMFS
chmod a+x $INITRAMFS/init
cp shutdown $INITRAMFS
chmod a+x $INITRAMFS/shutdown
ln -s ../init $INITRAMFS/bin/init
cp ../livekitlib $INITRAMFS/lib/
cp ../config $INITRAMFS/lib/

cd $INITRAMFS
find . -print | cpio -o -H newc 2>/dev/null | xz -T0 -f --extreme --check=crc32 >$INITRAMFS.img
echo $INITRAMFS.img

cd ..
rm -Rf $INITRAMFS
